#include "XmlNode.h"

#ifdef __WINSCW__
#include <e32svr.h>   //RDebug
#endif

#define STRING_BUFFER_LENGTH 1024;

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CXmlNode
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
CXmlNode* CXmlNode::NewL (const TDesC8& aNodeName, const TDesC8& aNodeValue, CXmlNode *aParent )
{
	CXmlNode* self = CXmlNode::NewLC (aNodeName, aNodeValue, aParent );
	CleanupStack::Pop ();
	return self;
}

CXmlNode* CXmlNode::NewLC (const TDesC8& aNodeName, const TDesC8& aNodeValue, CXmlNode *aParent )
{
	CXmlNode* self = new (ELeave) CXmlNode (aParent );
	CleanupStack::PushL (self );
	self->ConstructL (aNodeName, aNodeValue );
	return self;
	
}

CXmlNode::CXmlNode (CXmlNode *aParent ) :
	i_pName (NULL),
	i_pValue (NULL),
	i_pParent (aParent )
{

}

CXmlNode::~CXmlNode ()
{
		delete i_pName;
		delete i_pValue;
		for (TInt i = 0; i < i_pChildNode->Count (); i++ )
		{
			CXmlNode *pNode = i_pChildNode->At (i );
			delete pNode;
		}
		delete i_pChildNode;
		i_pChildNode = NULL;
		i_pName = NULL;
		i_pValue = NULL;
}

void CXmlNode::DeleteNode (TInt aIndex )
{
	CXmlNode *pNode = static_cast<CXmlNode*> (i_pChildNode->At (aIndex ) );
	delete pNode;
	i_pChildNode->Delete (aIndex );
}

void CXmlNode::ConstructL (const TDesC8& aNodeName, const TDesC8& aNodeValue )
{
	//�����ӽڵ�Ⱥ
	i_pChildNode = new (ELeave)CArrayPtrFlat<CXmlNode> (5);

	if(aNodeName != KNullDesC8)
	{
		i_pName = aNodeName.AllocL ();
	}
	if (aNodeValue != KNullDesC8 )
	{
		i_pValue = aNodeValue.AllocL ();
	}
}

void CXmlNode::AddNodeL (const TDesC8& aNodeName, const TDesC8& aNodeValue )
{
	CXmlNode *pNode = CXmlNode::NewL (aNodeName, aNodeValue );
	AddNodeL (pNode );
}

void CXmlNode::SetNodeValueL (const TDesC8 &aNodeValue )
{
	if (i_pValue )
		delete i_pValue;
	if(aNodeValue != KNullDesC8)
	{
		i_pValue = aNodeValue.AllocL ();
	//	i_pValue->Des().Copy(aNodeValue);
	}
}

void CXmlNode::AddNodeL (const TDesC8& aNodeName, const TDesC &aNodeValue )
{
	if(aNodeValue != KNullDesC)
	{
		HBufC8 *nodeValue8 = HBufC8::NewLC (aNodeValue.Length () );
		nodeValue8->Des ().Copy (aNodeValue );
		AddNodeL (aNodeName, nodeValue8->Des () );
	}
	else
	{
		AddNodeL (aNodeName, KNullDesC8);
	}
	CleanupStack::PopAndDestroy ();
}

void CXmlNode::AddNodeL (const TDesC8& aNodeName, const TInt aValue )
{
	TBuf8<16> buf;
	buf.AppendNum (aValue );
	AddNodeL (aNodeName, buf );
}

void CXmlNode::AddNodeL (CXmlNode* aNode )
{
	if (aNode == NULL )
		return;
	
	aNode->SetParentNode (this);//设置父节点
	i_pChildNode->AppendL (aNode );
}

HBufC8* CXmlNode::GetXMLStringL ()
{
	TInt len = Length ();
	
	HBufC8* pXmlStr = HBufC8::NewL (len );
	TPtr8 ptr (pXmlStr->Des () );
	ptr.Append (_L8("<"));
	ptr.Append (i_pName->Des () );
	ptr.Append (_L8(">"));
	//�����ӽڵ�
	if (i_pChildNode )
	{
		for (TInt i = 0; i < i_pChildNode->Count (); i++ )
		{
			CXmlNode *pNode = static_cast<CXmlNode*> (i_pChildNode->At (i ) );
			HBufC8* childStr = pNode->GetXMLStringL ();
			CleanupStack::PushL (childStr );
			ptr.Append (childStr->Des () );
			CleanupStack::PopAndDestroy (childStr );//childStr
		}
	}
	if (i_pValue )
		ptr.Append (i_pValue->Des () );
	//end code
	ptr.Append (_L8("</"));
	ptr.Append (i_pName->Des () );
	ptr.Append (_L8(">"));
	return pXmlStr;
}

TInt CXmlNode::Length ()
{
	TInt len = 5; //�̶�����<>, </>
	if (i_pName )
		len += 2 * i_pName->Length ();
	if (i_pValue )
		len += i_pValue->Length ();
	//�ӽڵ㳤��
	for (TInt i = 0; i < i_pChildNode->Count (); i++ )
	{
		CXmlNode *pNode = static_cast<CXmlNode*> (i_pChildNode->At (i ) );
		len += pNode->Length ();
	}
	return len;
}

CXmlNode * CXmlNode::ChildNode (const TDesC8 &aChildName )
{
	if(i_pChildNode)
	{
		for(TInt i = 0; i < i_pChildNode->Count(); i++)
		{
			CXmlNode *pChild = static_cast<CXmlNode*> (i_pChildNode->At (i ) );
			if(pChild == NULL)
				continue;
			if(pChild->i_pName->Compare(aChildName)== 0)
			{
				return pChild;
			}
		}
	}

	return NULL;
}

TDesC8 CXmlNode::NodeValue ()
{
	if(i_pValue)
		return i_pValue->Des();
	else
		return KNullDesC8;
}

TDesC8 CXmlNode::NodeName ()
{
	if(i_pName)
		return i_pName->Des();
	else
		return KNullDesC8;
}

TDesC8 CXmlNode::ChildNodeValue (const TDesC8 &aChildName )
{
	CXmlNode *pChildNode = ChildNode(aChildName);
	if(pChildNode)
		return pChildNode->NodeValue();
	else 
		return KNullDesC8;
	
}

/**
 * return the node index , not found : -1 
 */
TInt CXmlNode::FindNodeByNodeValue (const TDesC8& aNodeName, const TDesC8 &aNodeValue )
{
	if(aNodeName == KNullDesC8 || aNodeValue == KNullDesC8)
		return -1;
	
	if (i_pChildNode )
	{
		for (TInt i = 0; i < i_pChildNode->Count (); i++ )
		{
			CXmlNode *pChild = static_cast<CXmlNode*> (i_pChildNode->At (i ) );
			if (pChild == NULL )
				continue;
			if (pChild->i_pName->Compare (aNodeName ) == 0 )
			{
				if(pChild->i_pValue && pChild->i_pValue->Compare(aNodeValue) == 0)
					return i;
				else
					return -1;
			}
		}
	}
	
	return -1;
}

//子节点数
TInt CXmlNode::ChildCount ()
{
	if(i_pChildNode)
	{
		TInt count = i_pChildNode->Count ();
		return count;
	}
	else
	{
		return 0;
	}
}

CXmlNode * CXmlNode::ChildNode (TInt aIndex )
{
	if (i_pChildNode == NULL )
		return NULL;
	if (aIndex >= 0 || aIndex < i_pChildNode->Count() )
	{
		return static_cast<CXmlNode*> (i_pChildNode->At (aIndex ) );
	}
	else
		return NULL;
}

void CXmlNode::SetParentNode (CXmlNode* aNode )
{
	i_pParent = aNode;
}

CXmlNode* CXmlNode::ParentNode()
{
	return i_pParent;
}

//复制对象
CXmlNode* CXmlNode::AllocL()
{
	CXmlNode *pMem = new (ELeave)CXmlNode(NULL);
	CleanupStack::PushL(pMem);
	pMem->ConstructL(KNullDesC8, KNullDesC8);
	if(i_pName)
		pMem->i_pName = i_pName->Des().AllocL();
	if(i_pValue)
		pMem->i_pValue = i_pValue->Des().AllocL();
	
	for (TInt i = 0; i < i_pChildNode->Count (); i++ )
	{
		CXmlNode *pNode = static_cast<CXmlNode*> (i_pChildNode->At (i ) );
		pMem->i_pChildNode->AppendL(pNode->AllocL());
	}
	//未复制父节点
	CleanupStack::Pop();
	return pMem;
	
}
//
////////////////////////////////////////////////////////////////////////////////////
